<template>
  <div class="fall-chart-wrap">
    <div class="fall_warp" v-if="hasServerAndClientData" :style="{
      height: `${216 + (nsLength > 4 ? (nsLength - 4) * 20 : 0)}px`,
    }">
      <div class="src_dst_warp">
        <div class="src_dst_header">客户端</div>
        <div class="src_dst_main" style=" margin-left: auto">
          <div class="fall_item" :style="`
                  top: 24px;
                  right: 0px;
                  width: calc(${serverAndClientData.srcSentWidth}% + 115px + ${serverAndClientData.srcSentWidth ? 1 : 0
            }px),
                `">
            <div class="fall_item_label">发包时延</div>
            <div class="fall_item_progress" style=" background-color:#226EE7 " />
            <div class="fall_item_time">
              {{ formatUnit(exceptionTime?.srcSentTime, "ns") }}
            </div>
          </div>
          <div class="fall_item" :style="{
            top: '128px',
            right: '0px',
            width: `calc(${serverAndClientData.srcReceiveWidth}% + 115px + ${serverAndClientData.srcReceiveWidth ? 1 : 0
              }px)`,
          }">
            <div class="fall_item_label">收包时延</div>
            <div class="fall_item_progress" style=" background-color: #FF002E " />
            <div class="fall_item_time">
              {{ formatUnit(exceptionTime?.srcReceiveTime, "ns") }}
            </div>
          </div>
        </div>
      </div>
      <div class="src_dst_warp">
        <div class="connect_header">

          <template v-if='detailInfo?.appProtocol === "http"'>
            <svg width="100%" height="36">
              <defs>
                <marker id="arrowhead" viewBox="0 0 10 10" refX="0" refY="5" markerWidth="3" markerHeight="3"
                  orient="auto">
                  <path d="M 0 0 L 5 5 L 0 10 z" fill="#13C2C2" />
                </marker>
              </defs>
              <path d="M 20 18 L 305 18" stroke="#13C2C2" strokeWidth="4" markerEnd="url(#arrowhead)" />
            </svg>
            <div class="connect_header_data">
              建连耗时：
              {{ formatUnit(exceptionTime?.connectTime, "ns") }}
            </div>
          </template>

        </div>
        <div class="src_dst_main">
          <div class="fall_item" :style="{
            top: '50px',
            width: `calc(${serverAndClientData.netTransWidth}% + 76px + ${serverAndClientData.netTransWidth ? 1 : 0
              }px)`,
          }">
            <div class="fall_item_label">网络传输时延</div>
            <div class="fall_item_progress" style="background-color: #D7A707" />
          </div>
          <div class="fall_item" :style="{
            top: '102px', width: `calc(${serverAndClientData.netTransWidth}% + 76px + ${serverAndClientData.netTransWidth ? 1 : 0
              }px)`,
          }">
            <div class="fall_item_label">网络传输时延</div>
            <div class="fall_item_progress" style=' background-color: #D7A707' />
          </div>
          <div class="fall_item" :style="{ top: '154px', width: '100%' }">
            <icon-info-circle />
            &nbsp;
            <span>
              两次网络传输时延总和为
              {{ formatUnit(exceptionTime?.netTransTime, "ns") }}，
              <span class="span_a" >
                查看网络
              </span>
            </span>
          </div>
        </div>
      </div>
      <div class="src_dst_warp">
        <div class="src_dst_header">服务端</div>
        <div class="src_dst_main">
          <div class="fall_item" :style="{
            top: '76px', width: `calc(${serverAndClientData.dstHandleWidth}% + 130px + ${serverAndClientData.dstHandleWidth ? 1 :
              0}px)`,
          }">
            <div class="span_a fall_item_label" @click="() => emits('on-change-tab', 'relate')">
              <icon-link />
              &nbsp;处理时延
            </div>
            <div class="fall_item_progress" :style="{ backgroundColor: '#D9E40F' }"></div>
            <div class="fall_item_time">
              {{ formatUnit(exceptionTime?.dstHandleTime, "ns") }}
            </div>
          </div>
          <div class="path_start" :style="{ top: '96px', left: '68px' }" v-if="nsLength"></div>
          <svg>
            <defs>
              <marker id="triangle" viewBox="0 0 10 10" refX="0" refY="5" markerWidth="4" markerHeight="4"
                orient="auto">
                <path d="M 0 0 L 5 5 L 0 10 z" fill="#E9E9E9" />
              </marker>
            </defs>
          </svg>

          <template :key={idx} v-for="(item, idx) in northStarIndex">
            <svg class="north_star_line" :style="{ top: `${96 + 20 * idx}px`, left: '68px' }">
              <path :d='idx > 0
                ? "M 2,-2, V 18, A 2,2,0,0,0,4,20 L 15,20"
                : "M 2,4, V 18, A 2,2,0,0,0,4,20 L 15,20"
                ' markerEnd="url(#triangle)" class="north_star_path" />
            </svg>
            <div class="north_star_progress" :style="{ top: `${110 + 20 * idx}px`, left: '88px' }">
              <div class="north_star_progress_text">{{ item.label }}</div>
              <div class="north_star_progress_inner" :style="{ width: `${item.percent}%`, }" />
              <div class="north_star_progress_text" :style="{ left: 'calc(100% - 8px)' }">
                {{ formatUnit(item.value, "ns") }} |{{ " " }}
                {{ formatUnit(item.percent, "%") }}
              </div>
            </div>
          </template>

        </div>
      </div>
    </div>
    <div class="fall_warp" v-else-if="onlyHasServerData" :style='{
      height: `${192 + (nsLength > 2 ? (nsLength - 2) * 20 : 0)}px`,
    }'>
      <div class="src_dst_warp">
        <div class="src_dst_header">客户端</div>
        <div class="fall_item" :style="{ top: '60px', right: '0px', width: '100%' }">
          <div class="fall_item_label">发包时延</div>
          <div class="fall_item_progress" :style="{ backgroundColor: '#F4F4F4' }"></div>
          <div class="fall_item_time">{{ formatUnit(0, "ns") }}</div>
        </div>
        <div class="fall_item" :style='{ top: "164px", right: "px", width: "100%" }'>
          <div class="fall_item_label">收包时延</div>
          <div class="fall_item_progress" :style='{ backgroundColor: "#F4F4F4" }' />
          <div class="fall_item_time">{{ formatUnit(0, "ns") }}</div>
        </div>
      </div>
      <div class="src_dst_warp" :style='{ flexGrow: 2, marginLeft: "24px" }'>
        <div class="src_dst_header">服务端</div>
        <div class="src_dst_main">
          <div class="fall_item" :style='{
            top: "50px",
            width: `calc(${serverAndClientData.dstSentWidth}% + ${serverAndClientData.dstSentWidth ? 1 : 0}px)`,
          }'>
            <div class="fall_item_label">发包时延</div>
            <div class="fall_item_progress" :style='{ backgroundColor: "#FF002E" }' />
            <div class="fall_item_time">
              {{ formatUnit(exceptionTime?.dstSentTime, "ns") }}
            </div>
          </div>
          <div class="fall_item" :style='{
            top: `76px`,
            left: `${dstSentWidth}%`,
            width: `calc(${serverAndClientData.dstHandleWidth}% + ${serverAndClientData.dstHandleWidth ? 1 : 0
              }px)`,
          }'>
            <div class="span_a fall_item_label" @click="() => emits('on-change-tab', 'relate')">
              <icon-link />
              &nbsp;处理时延
            </div>
            <div class="fall_item_progress" :style='{ backgroundColor: "#D9E40F" }'></div>
            <div class="fall_item_time">
              {{ formatUnit(exceptionTime?.dstHandleTime, "ns") }}
            </div>
          </div>

          <div class="path_start" v-if="nsLength" :style='{
            top: `96px`,
            left: `calc(${serverAndClientData.dstSentWidth}% + 68px)`,
          }'></div>
          <svg>
            <defs>
              <marker id="triangle" viewBox="0 0 10 10" refX="0" refY="5" markerWidth="4" markerHeight="4"
                orient="auto">
                <path d="M 0 0 L 5 5 L 0 10 z" fill="#E9E9E9" />
              </marker>
            </defs>
          </svg>

          <template :key="idx" v-for="(item, idx) in northStarIndex">
            <svg class="north_star_line" :style='{
              top: `${96 + (idx > 0 ? 12 : 0) + 20 * idx}px`,
              left: `calc(${serverAndClientData.dstSentWidth}% + 68px)`,
            }'>
              <path :d='idx > 0
                ? "M 2,-2, V 20, A 2,2,0,0,0,4,22 L 15,22"
                : "M 2,4, V 32, A 2,2,0,0,0,4,34 L 15,34"
                ' markerEnd="url(#triangle)" class="north_star_path" />
            </svg>
            <div class="north_star_progress" :style='{
              width: "30%", top: `${124 + 20 * idx}px`, left:
                `calc(${serverAndClientData.dstSentWidth}% + 88px)`,
            }'>
              <div class="north_star_progress_text">{{ item.label }}</div>
              <div class="north_star_progress_inner" :style='{ width: `${item.percent}%`, }' />
              <div class="north_star_progress_text" :style='{ left: "calc(100% - 8px)" }'>
                {{ formatUnit(item.value, "ns") }} |{{ " " }}
                {{ formatUnit(item.percent, "%") }}
              </div>
            </div>
          </template>
          <div class="fall_item" :style='{
            top: `102px`, left: `${serverAndClientData.dstSentWidth + serverAndClientData.dstHandleWidth}%`, width:
              `calc(${serverAndClientData.dstReceiveWidth}% + ${serverAndClientData.dstReceiveWidth ? 1 : 0}px)`,
          }'>
            <div class="fall_item_label">收包时延</div>
            <div class="fall_item_progress" :style='{ backgroundColor: "#226EE7" }' />
            <div class="fall_item_time">
              {{ formatUnit(exceptionTime?.dstReceiveTime, "ns") }}
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="fall_warp" v-else-if="onlyHasClientData" :style="{ height: '152px' }">
      <div class="src_dst_warp">
        <div class="src_dst_header">客户端</div>
        <div class="src_dst_main" :style='{ marginLeft: "auto" }'>
          <div class="fall_item" :style='{
            top: `24px`,
            right: `0px`,
            width: `calc(${serverAndClientData.srcSentWidth}% + 115px + ${serverAndClientData.srcSentWidth ? 1 : 0
              }px)`,
          }'>
            <div class="fall_item_label">发包时延</div>
            <div class="fall_item_progress" :style='{ backgroundColor: "#226EE7" }'></div>
            <div class="fall_item_time">
              {{ formatUnit(exceptionTime?.srcSentTime, "ns") }}
            </div>
          </div>
          <div class="fall_item" :style='{
            top: `78px`,
            right: `0px`,
            width: `calc(${serverAndClientData.srcReceiveWidth}% + 115px + ${serverAndClientData.srcReceiveWidth ? 1 : 0
              }px)`,
          }'>
            <div class="fall_item_label">收包时延</div>
            <div class="fall_item_progress" :style='{ backgroundColor: "#FF002E" }'></div>
            <div class="fall_item_time">
              {{ formatUnit(exceptionTime?.srcReceiveTime, "ns") }}
            </div>
          </div>
        </div>
      </div>
      <div class="src_dst_warp">
        <div class="connect_header">
          <template v-if='detailInfo?.appProtocol === "http"'>
            <svg width="100%" height="36">
              <defs>
                <marker id="arrowhead" viewBox="0 0 10 10" refX="0" refY="5" markerWidth="3" markerHeight="3"
                  orient="auto">
                  <path d="M 0 0 L 5 5 L 0 10 z" fill="#13C2C2" />
                </marker>
              </defs>
              <path d="M 20 18 L 305 18" stroke="#13C2C2" strokeWidth="4" markerEnd="url(#arrowhead)" />
            </svg>
            <div class="connect_header_data">
              建连耗时：
              {{ formatUnit(exceptionTime?.connectTime, "ns") }}
            </div>
          </template>
        </div>
        <div class="src_dst_main">
          <div class="fall_item" :style='{
            top: `50px`,
            right: `calc(-${serverAndClientData.srcWaitingWidth / 2}% - 115px - 63px)`,
            width: `calc(${serverAndClientData.srcWaitingWidth}% + 139px + ${serverAndClientData.srcWaitingWidth ? 1 : 0
              }px)`,
          }'>
            <div class="fall_item_label">等待响应时延</div>
            <div class="fall_item_progress" :style='{ backgroundColor: "#AB0FE4" }'></div>
            <div class="fall_item_time">
              {{ formatUnit(exceptionTime?.srcWaitingTime, "ns") }}
            </div>
          </div>
          <div class="fall_item" :style='{ top: `102px` }'>
            <icon-info-circle />
            &nbsp;
            <span>等待响应时延的长度为网络传输时延和服务端的总和</span>
          </div>
        </div>
      </div>
      <div class="src_dst_warp">
        <div class="src_dst_header">服务端</div>
      </div>
    </div>
    <ga-empty v-else></ga-empty>
  </div>
</template>

<script setup>
import { computed, toRefs, watch } from 'vue';
import { pick, sum, values } from 'lodash'
import { formatUnit } from '@/utils/format'
const props = defineProps({
  exceptionTime: {
    type: Object,
    default: () => ({})
  },
  detailInfo: {
    type: Object,
    default: () => ({})
  }
})
const emits = defineEmits(['on-change-tab'])
const propsRef = toRefs(props)
const { exceptionTime } = propsRef


const northStartIndex = computed(() => {
  const {

    dstHandleTime,

    profilingMetric,
  } = exceptionTime.value;
  const { cpuNs, netNs, fileNs, epollNs, futexNs, idleNs, otherNs, runqNs } =
    profilingMetric || {};
  let northStarIndex = [
    {
      label: "cpu执行",
      value: cpuNs,
      percent: (Number(cpuNs) / Number(dstHandleTime)) * 100,
    },
    {
      label: "等待唤醒",
      value: futexNs,
      percent: (Number(futexNs) / Number(dstHandleTime)) * 100,
    },
    {
      label: "网络I/O",
      value: netNs,
      percent: (Number(netNs) / Number(dstHandleTime)) * 100,
    },
    {
      label: "文件I/O",
      value: fileNs,
      percent: (Number(fileNs) / Number(dstHandleTime)) * 100,
    },
    {
      label: "等待",
      value: idleNs,
      percent: (Number(idleNs) / Number(dstHandleTime)) * 100,
    },
    {
      label: "epoll等待",
      value: epollNs,
      percent: (Number(epollNs) / Number(dstHandleTime)) * 100,
    },
    {
      label: "其他",
      value: otherNs,
      percent: (Number(otherNs) / Number(dstHandleTime)) * 100,
    },
    {
      label: "等待cpu调度",
      value: runqNs,
      percent: (Number(runqNs) / Number(dstHandleTime)) * 100,
    },
  ];
  northStarIndex = filter(
    northStarIndex,
    (item) => isNumber(item.value) && item.value > 0
  );
  northStarIndex.sort((a, b) => Number(b.value) - Number(a.value));
  return northStarIndex
})
const nsLength = computed(() => northStartIndex.length)
const hasServerAndClientData = computed(() => {
  const {
    srcReceiveTime,
    srcSentTime,
    dstHandleTime,
    dstReceiveTime,
    dstSentTime,
    netTransTime,
  } = exceptionTime.value;
  return Boolean((dstReceiveTime || dstHandleTime || dstSentTime) &&
    (srcSentTime || srcReceiveTime) &&
    Number(netTransTime) >= 0)
})

const onlyHasServerData = computed(() => {
  const {
    srcReceiveTime,
    srcSentTime,
    dstHandleTime,
    dstReceiveTime,
    dstSentTime,
  } = exceptionTime.value;
  return Boolean((dstReceiveTime || dstHandleTime || dstSentTime) &&
    !srcSentTime &&
    !srcReceiveTime)
})

const onlyHasClientData = computed(() => {
  const {
    srcReceiveTime,
    srcSentTime,

    netTransTime,
  } = exceptionTime.value;
  return Boolean(srcSentTime || srcReceiveTime || Number(netTransTime) < 0)
})
console.log(hasServerAndClientData, 'data', onlyHasServerData, 'server', onlyHasClientData, 'client');

const dataFiles = computed(() => {
  if (hasServerAndClientData.value) {
    return ['srcReceiveTime',
      'srcSentTime',
      'dstHandleTime',
      'netTransTime']
  } else if (onlyHasServerData.value) {
    return ['dstReceiveTime', 'dstHandleTime', 'dstSentTime']
  } else {
    return ['srcSentTime', 'srcReceiveTime', 'srcWaitingTime']
  }
})
const serverAndClientData = computed(() => {

  const fieldMap = {
    srcSentTime: 'srcSentWidth',
    srcReceiveTime: 'srcReceiveWidth',
    dstHandleTime: 'dstHandleWidth',
    netTransTime: 'netTransWidth',
    srcWaitingTime: 'srcWaitingWidth',
    dstReceiveTime: "dstReceiveWidth",
    dstSentTime: 'dstSentWidth'
  }

  const data = pick(exceptionTime.value, dataFiles.value)
  const times = sum(values(data));
  const result = {}
  dataFiles.value.forEach((item) => {
    const key = fieldMap[item]
    if (item === 'netTransWidth') {

      result[key] = (Number(data[item]) / times) * 100 / 2
    } else {
      result[key] = (Number(data[item]) / times) * 100
    }
  })

  return result
})
watch(exceptionTime, (newV) => {
  console.log(hasServerAndClientData, onlyHasClientData, onlyHasServerData, serverAndClientData);

})
watch(() => props.detailInfo, (newV) => {
  console.log('update detail info in waterfall ', newV);

})
</script>

<style scoped lang="scss">
.fall-chart-wrap {
  width: 100%;
  border: 1px dashed #dcdcdc;
  min-height: 127px;
  margin-bottom: 15px;
  padding: 24px;
  display: flex;
  justify-content: center;
  align-items: center;

  .fall_warp {
    display: flex;
    width: 100%;

    .src_dst_warp {
      flex-basis: 0;
      flex-grow: 1;
      position: relative;

      .src_dst_header {
        height: 36px;
        line-height: 36px;
        font-weight: 500;
        font-size: 14px;
        color: rgba(0, 0, 0, 0.85);
        width: 100%;
        background-color: rgba(34, 110, 231, 0.06);
        padding: 0 8px;
      }

      .src_dst_main {
        height: calc(100% - 36px);
        width: calc(100% - 115px);
        overflow: visible;
        position: relative;
      }

      .fall_item {
        display: flex;
        align-items: center;
        min-width: max-content;
        font-weight: 400;
        font-size: 12px;
        height: 14px;
        position: absolute;

        .fall_item_label {
          margin-right: 4px;
          min-width: 48px;
        }

        .fall_item_progress {
          flex-grow: 1;
          height: 14px;
        }

        .fall_item_time {
          margin-left: 4px;
          min-width: 59px;
          // text-align: end;
        }
      }

      .connect_header {
        height: 36px;
        width: 100%;
        position: relative;

        .connect_header_data {
          position: absolute;
          left: 50%;
          top: 50%;
          transform: translate(-50%, -50%);
          background-color: #FFFFFF;
          padding: 0 4px;
          font-weight: 400;
          font-size: 12px;
        }
      }

      .path_start {
        width: 4px;
        height: 4px;
        background-color: #D5D5D5;
        border-radius: 50%;
        position: absolute;
      }

      .north_star_line {
        position: absolute;
        width: 18px;
        height: 50%;
        overflow: visible;

        .north_star_path {
          stroke: #E9E9E9;
          stroke-width: 1px;
          fill: none;
        }
      }

      .north_star_progress {
        width: 60%;
        height: 12px;
        background-color: #F4F4F4;
        position: absolute;
        overflow: visible;

        .north_star_progress_text {
          height: 12px;
          line-height: 12px;
          font-size: 12px;
          transform: scale(0.8);
          position: absolute;
          top: 0;
          width: max-content;
        }

        .north_star_progress_inner {
          height: 100%;
          background-color: #D9E40F;
        }
      }
    }
  }
}
</style>
